package com.qq.service;

import com.qq.common.Message;
import com.qq.common.MessageType;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;


/**
 * 功能：该类负责与客户端的持续通信
 *
 * @author 可凡
 */
public class ServerConnectClientThread extends Thread {
    private final Socket socket;
    private final String userId;

    public ServerConnectClientThread(Socket socket, String userId) {
        this.socket = socket;
        this.userId = userId;
    }

    @Override
    public void run() {
        while (true) {
            try {
                ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
                Message message = (Message) objectInputStream.readObject();
                //判断收到的消息是否时在线用户列表请求
                if (message.getMesType().equals(MessageType.MESSAGE_GET_ONLINE_USERS)) {
                    System.out.print("\n收到用户" + userId + "的在线用户列表请求");
                    //得到一个对象输出流和message对象
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                    Message allUsersMes = new Message();
                    //将message的消息类型设置为返回消息类型并发送
                    allUsersMes.setMesType(MessageType.MESSAGE_RET_ONLINE_USERS);
                    allUsersMes.setContent(ManageServerThread.getAllUsers());
                    objectOutputStream.writeObject(allUsersMes);
                    objectOutputStream.flush();
                }
                //判断收到的消息是否是下线请求，是则关闭其对应的socket并从HashMap中删除对应的键值对
                if (message.getMesType().equals(MessageType.MESSAGE_CLIENT_EXIT)) {
                    System.out.print("\n已经接收到用户：" + userId + " 的下线请求");
                    ServerConnectClientThread server = ManageServerThread.getServer(userId);
                    server.socket.close();
                    ManageServerThread.removeServer(userId);
                }
                //判断收到的消息是否是普通的消息
                if (message.getMesType().equals(MessageType.MESSAGE_COMM_MES)) {
                    //获取一个新的message对象，将消息类型设置为普通类型，并设置内容和发送者
                    Message sendMessage = new Message();
                    sendMessage.setMesType(MessageType.MESSAGE_COMM_MES);
                    sendMessage.setContent(message.getContent());
                    sendMessage.setSender(userId);
                    //利用所接收消息中的接收者，从集合中获取其接收者所对应的socket
                    //使用while循环，解决离线消息，使其等待对方上线后发送消息
                    while (true) {
                        try {
                            ServerConnectClientThread server = ManageServerThread.getServer(message.getGetter());
                            ObjectOutputStream objectOutputStream = new ObjectOutputStream(server.socket.getOutputStream());
                            objectOutputStream.writeObject(sendMessage);
                            objectOutputStream.flush();
                            break;
                        } catch (Exception e) {
                            System.out.println("\n消息发送失败！等待对方上线" + e.getMessage());
                            try {
                                Thread.sleep(8000);
                            } catch (InterruptedException ex) {
                                System.out.println("线程休眠时出现异常：" + ex.getMessage());
                            }
                        }
                    }
                }
                //判断该消息是否时群发消息，是则将其转发给所有在线用户
                if (message.getMesType().equals(MessageType.MESSAGE_MASS_MES)) {
                    //获取全部在线用户的userId
                    String[] s = ManageServerThread.getAllUsers().split(" ");
                    //遍历userId获取对应的线程
                    for (String string : s) {
                        if (!string.equals(userId)) {
                            try {
                                ServerConnectClientThread server = ManageServerThread.getServer(string);
                                //通过对应线程的socket获取输出字节流
                                ObjectOutputStream objectOutputStream = new ObjectOutputStream(server.socket.getOutputStream());
                                objectOutputStream.writeObject(message);
                                objectOutputStream.flush();
                            } catch (IOException e) {
                                System.out.println("群发消息发送失败！" + e.getMessage());
                            }
                        }
                    }
                }

                //判断所接收消息类型是否是发送文件类型
                if (message.getMesType().equals(MessageType.MESSAGE_SEND_TEXT_FILE_MES) || message.getMesType().equals(MessageType.MESSAGE_SEND_BINARY_FILE_MES)) {
                    try {
                        ServerConnectClientThread server = ManageServerThread.getServer(message.getGetter());
                        ObjectOutputStream objectOutputStream = new ObjectOutputStream(server.socket.getOutputStream());
                        objectOutputStream.writeObject(message);
                        objectOutputStream.flush();
                        System.out.println("\n文件发送成功！");
                    } catch (IOException e) {
                        System.out.println("\n文件发送失败！" + e.getMessage());
                    }
                }
            } catch (IOException e) {
                System.out.print("\n用户：" + userId + "下线！" + e.getMessage());
                ManageServerThread.removeServer(userId);
                break;
            } catch (ClassNotFoundException e) {
                System.out.println("所接收消息在转换时发生异常！" + e.getMessage());
            }
        }
    }
}
